#include "Renderer_PCH.h"
#include "QueueMgr.h"

/*--------------------------------------------------------------------------*/

QueueMgr::QueueMgr()
{

}

/*--------------------------------------------------------------------------*/

QueueMgr::~QueueMgr()
{

}

/*--------------------------------------------------------------------------*/

void QueueMgr::InitQueueMgr()
{

}

/*--------------------------------------------------------------------------*/

void QueueMgr::ClearQueue()
{
	m_tasks.clear();
}

/*--------------------------------------------------------------------------*/

void QueueMgr::AddTask(const IModelMatrixOwner* matowner, const RMaterial* material, const RVertexArray* vertexarray, ETopology::Type topology, uint vertices, uint flags )
{
	m_tasks.push_back(RTask());

	RTask& task = m_tasks.back();
	task.matowner = matowner;
	task.material = material;
	task.vao = vertexarray;
	task.topology = topology;
	task.vertices = vertices;
	task.flags = flags;
	task.done = false;
}

/*--------------------------------------------------------------------------*/

void QueueMgr::Flush()
{
	for (auto iter = m_tasks.begin(); iter != m_tasks.end(); ++iter)
	{
		if (iter->done)
		{
			continue;
		}

		if (iter->material->GetInstancedVersion())
		{
			uint toInstance = 0;
			for (auto inst = iter; inst != m_tasks.end(); ++inst)
			{
				if (inst->done)
				{
					continue;
				}

				if (inst->material == iter->material && inst->vao == iter->vao)
				{
					toInstance++;
				}
			}

			DynamicSurface* ds = g_Renderer->GetDynGeometryMgr()->BeginGeometry(toInstance, EVertex::Instancing);
			GLM_MAT4x4* mat = ds->vInstancing();
			
			uint counter = 0;
			for (auto inst = iter; inst != m_tasks.end(); ++inst)
			{
				if (inst->done)
				{
					continue;
				}

				if (inst->material == iter->material && inst->vao == iter->vao)
				{
					inst->done = true;
					inst->matowner->WriteModelMatrix((float*) &mat[counter]);
					++counter;

					if (counter == toInstance)
						break;
				}

				__Check(counter <= toInstance);
			}

			RVertexArray* instvao = g_Renderer->GetDynGeometryMgr()->EndGeometry();
			g_Renderer->BindMaterial(iter->material->GetInstancedVersion());
			g_Renderer->Draw(iter->vao, iter->topology, iter->vertices, toInstance, instvao);

			delete instvao;
		}
		else
		{
			if (iter->matowner)
			{
				iter->matowner->WriteModelMatrix(g_Renderer->GetModelMatrix());
			}
			else
			{
				g_Renderer->SetModelMatrix(GLM_MAT4x4());
			}

			g_Renderer->BindMaterial(iter->material->GetNormalVersion());
			g_Renderer->Draw(iter->vao, iter->topology, iter->vertices, 0, NULL);
			iter->done = true;
		}

		if (iter->flags & ETask::DynamicVAO)
		{
			delete iter->vao;
			iter->vao = NULL;
		}
	}

	m_tasks.clear();
}

/*--------------------------------------------------------------------------*/